home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / lib / rcscripts / awk / gendepends.awk < prev    next >
Text File  |  2006-04-25  |  11KB  |  493 lines

  1. # Copyright 1999-2004 Gentoo Foundation
  2. # Distributed under the terms of the GNU General Public License v2
  3. # $Header$
  4.  
  5. # bool check_service(name)
  6. #
  7. #   Returns true if the service exists
  8. #
  9. function check_service(name,    x)
  10. {
  11.     for (x = 1; x <= RC_NUMBER; x++) {
  12.         if (DEPTREE[x,NAME] == name)
  13.             return 1
  14.     }
  15.  
  16.     return 0
  17. }
  18.  
  19. # int get_service_index(name)
  20. #
  21. #   Return the index position in DEPTREE
  22. #
  23. function get_service_index(name,    x)
  24. {
  25.     for (x = 1; x <= RC_NUMBER; x++) {
  26.         if (DEPTREE[x,NAME] == name)
  27.             return x
  28.     }
  29.  
  30.     return 0
  31. }
  32.  
  33. # bool check_depend(service1, type, service2)
  34. #
  35. #   Returns true if 'service1' need/use/is_before/is_after 'service2'
  36. #
  37. function check_depend(service1, type, service2,    tmpsplit, x)
  38. {
  39.     if (check_service(service1)) {
  40.         x = get_service_index(service1)
  41.  
  42.         if ((x,type) in DEPTREE) {
  43.             split(DEPTREE[x,type], tmpsplit)
  44.  
  45.             for (x in tmpsplit) {
  46.                 if (tmpsplit[x] == service2)
  47.                     return 1
  48.             }
  49.         }
  50.     }
  51.  
  52.     return 0
  53. }
  54.  
  55. # bool add_deptree_item(rcnumber, type, item)
  56. #
  57. #   Add an item(s) 'item' to the DEPTREE array at index [rcnumber,type]
  58. #
  59. function add_deptree_item(rcnumber, type, item)
  60. {
  61.     if (DEPTREE[rcnumber,type] != "")
  62.         DEPTREE[rcnumber,type] = DEPTREE[rcnumber,type] " " item
  63.     else
  64.         DEPTREE[rcnumber,type] = item
  65.  
  66.     return 1
  67. }
  68.  
  69. # bool add_provide(service, provide)
  70. #
  71. #   Add a name of a virtual service ('provide') that 'service' Provides
  72. #
  73. function add_provide(service, provide)
  74. {
  75.     # We cannot have a service Provide a virtual service with the same name as
  76.     # an existing service ...
  77.     if (check_service(provide)) {
  78.         eerror(" Cannot add provide '" provide "', as a service with the same name exists!")
  79.         return 0
  80.     }
  81.         
  82.     if (check_provide(provide)) {
  83.         # We cannot have more than one service Providing a virtual ...
  84.         ewarn(" Service '" get_provide(provide) "' already provided by '" provide "'!;")
  85.         ewarn(" Not adding service '" service "'...")
  86.         # Do not fail here as we do have a service that resolves the virtual
  87.     } else {
  88.         # Sanity check
  89.         if (check_service(service)) {
  90.             PROVIDE_LIST[provide] = service
  91.         } else {
  92.             eerror(" Cannot add provide '" provide "', as service '" service "' does not exist!")
  93.             return 0
  94.         }
  95.     }
  96.  
  97.     return 1
  98. }
  99.  
  100. # string get_provide(provide)
  101. #
  102. #   Return the name of the service that Provides 'provide'
  103. #
  104. function get_provide(provide)
  105. {
  106.     if (provide in PROVIDE_LIST)
  107.         if (check_service(PROVIDE_LIST[provide]))
  108.             return PROVIDE_LIST[provide]
  109.     
  110.     return ""
  111. }
  112.  
  113. # bool check_provide(provide)
  114. #
  115. #   Return true if any service Provides the virtual service with name 'provide'
  116. #
  117. function check_provide(provide)
  118. {
  119.     if (provide in PROVIDE_LIST)
  120.         return 1
  121.     
  122.     return 0
  123. }
  124.  
  125. # bool add_parallel(service, parallel)
  126. #
  127. #   Add 'yes' or 'no' to the parallel modifier of 'service'.
  128. #
  129. function add_parallel(service, parallel,    sindex)
  130. {
  131.     if ((parallel != "yes") && (parallel != "no")) {
  132.         eerror(" The 'parallel' modifier can only take 'yes' or 'no' as argument!")
  133.         eerror(" Please fix this in the '" service "' service.")
  134.         return 0
  135.     }
  136.     
  137.     if (check_service(service)) {
  138.         sindex = get_service_index(service)
  139.         
  140.         RESOLVED_DEPTREE[sindex,PARALLEL] = parallel
  141.  
  142.         return 1
  143.     } else
  144.         eerror(" Service '" service "' do not exist!")
  145.  
  146.     return 0
  147. }
  148.  
  149. # bool add_db_entry(service, type, item)
  150. #
  151. #   Add a entry to RESOLVED_DEPTREE
  152. #
  153. function add_db_entry(service, type, item,    x, sindex, tmpsplit)
  154. {
  155.     if (!check_service(service)) {
  156.         eerror(" Service '" service "' do not exist!")
  157.         return 0
  158.     }
  159.  
  160.     sindex = get_service_index(service)
  161.  
  162.     if ((sindex,type) in RESOLVED_DEPTREE) {
  163.         split(RESOLVED_DEPTREE[sindex,type], tmpsplit)
  164.  
  165.         for (x in tmpsplit) {
  166.             if (tmpsplit[x] == item)
  167.                 return 1
  168.         }
  169.         
  170.         RESOLVED_DEPTREE[sindex,type] = RESOLVED_DEPTREE[sindex,type] " " item
  171.     } else {
  172.         RESOLVED_DEPTREE[sindex,type] = item
  173.     }
  174.  
  175.     return 1
  176. }
  177.  
  178. # void resolve_depend(type, service, deplist)
  179. #
  180. #   Verify a depend entry(s) 'deplist' for service 'service' of type 'type',
  181. #   and then add it to the DB.
  182. #
  183. function resolve_depend(type, service, deplist,    x, deparray)
  184. {
  185.     if ((type == "") || (service == "") || (deplist == ""))
  186.         return
  187.  
  188.     # If there are no existing service 'service', resolve possible
  189.     # provided services
  190.     if (!check_service(service)) {
  191.         if (check_provide(service))
  192.             service = get_provide(service)
  193.         else
  194.             return
  195.     }
  196.  
  197.     split(deplist, deparray)
  198.  
  199.     for (x in deparray) {
  200.  
  201.         # If there are no existing service 'deparray[x]', resolve possible
  202.         # provided services
  203.         if (!check_service(deparray[x])) {
  204.             if (check_provide(deparray[x]))
  205.                 deparray[x] = get_provide(deparray[x])
  206.         }
  207.  
  208.         # Handle 'need', as it is the only dependency type that
  209.         # should handle invalid database entries currently.
  210.         if (!check_service(deparray[x])) {
  211.  
  212.             if (((type == NEED) || (type == NEEDME)) && (deparray[x] != "net")) {
  213.  
  214.                 ewarn(" Can't find service '" deparray[x] "' needed by '" service "';  continuing...")
  215.  
  216.                 # service is broken due to missing 'need' dependencies
  217.                 add_db_entry(service, BROKEN, deparray[x])
  218.  
  219.                 continue
  220.             }
  221.             else if (deparray[x] != "net")
  222.                 continue
  223.         }
  224.  
  225.         # Ugly bug ... if a service depends on itself, it creates
  226.         # a 'mini fork bomb' effect, and breaks things...
  227.         if (deparray[x] == service) {
  228.  
  229.             # Dont work too well with the '*' use and need
  230.             if ((type != BEFORE) && (type != AFTER))
  231.                 ewarn(" Service '" deparray[x] "' can't depend on itself;  continuing...")
  232.  
  233.             continue
  234.         }
  235.  
  236.         # Currently only these depend/order types are supported
  237.         if ((type == NEED) || (type == USE) || (type == BEFORE) || (type == AFTER)) {
  238.     
  239.             if (type == BEFORE) {
  240.                 # NEED and USE override BEFORE (service BEFORE deparray[x])
  241.                 if (check_depend(service, NEED, deparray[x]) ||
  242.                     check_depend(service, USE, deparray[x]))
  243.                     continue
  244.             }
  245.             
  246.             if (type == AFTER) {
  247.                 # NEED and USE override AFTER (service AFTER deparray[x])
  248.                 if (check_depend(deparray[x], NEED, service) ||
  249.                     check_depend(deparray[x], USE, service))
  250.                     continue
  251.             }
  252.  
  253.             # NEED override USE (service USE deparray[x])
  254.             if ((type == USE) && (check_depend(deparray[x], NEED, service))) {
  255.                 ewarn(" Service '" deparray[x] "' NEED service '" service "', but service '" service "' wants")
  256.                 ewarn(" to USE service '" deparray[x] "'!")
  257.                 continue
  258.             }
  259.  
  260.             # We do not want to add circular depends ...
  261.             if (check_depend(deparray[x], type, service)) {
  262.                     
  263.                     if ((service,deparray[x],type) in CIRCULAR_DEPEND)
  264.                         continue
  265.                         
  266.                     if ((deparray[x],service,type) in CIRCULAR_DEPEND)
  267.                         continue
  268.                     
  269.                     ewarn(" Services '" service "' and '" deparray[x] "' have circular")
  270.                     ewarn(" dependency of type '" TYPE_NAMES[type] "';  continuing...")
  271.                     
  272.                     CIRCULAR_DEPEND[service,deparray[x],type] = "yes"
  273.                     
  274.                     continue
  275.             }
  276.  
  277.             add_db_entry(service, type, deparray[x])
  278.  
  279.             # Reverse mapping
  280.             if (type == NEED)
  281.                 add_db_entry(deparray[x], NEEDME, service)
  282.  
  283.             # Reverse mapping
  284.             if (type == USE)
  285.                 add_db_entry(deparray[x], USEME, service)
  286.  
  287.             # Reverse mapping
  288.             if (type == BEFORE)
  289.                 add_db_entry(deparray[x], AFTER, service)
  290.  
  291.             # Reverse mapping
  292.             if (type == AFTER)
  293.                 add_db_entry(deparray[x], BEFORE, service)
  294.         }
  295.     }
  296. }
  297.  
  298. BEGIN {
  299.     NAME = 1
  300.     RC_NUMBER = 0
  301.  
  302.     # Types ...
  303.     NEED = 2
  304.     NEEDME = 3
  305.     USE = 4
  306.     USEME = 5
  307.     BEFORE = 6
  308.     AFTER = 7
  309.     BROKEN = 8
  310.     PARALLEL = 9
  311.     MTIME = 10
  312.     PROVIDE = 11    # Not part of Types as when finally printed ...
  313.     TYPES_MIN = 2
  314.     TYPES_MAX = 10
  315.  
  316.     TYPE_NAMES[NEED] = "ineed"
  317.     TYPE_NAMES[NEEDME] = "needsme"
  318.     TYPE_NAMES[USE] = "iuse"
  319.     TYPE_NAMES[USEME] = "usesme"
  320.     TYPE_NAMES[BEFORE] = "ibefore"
  321.     TYPE_NAMES[AFTER] = "iafter"
  322.     TYPE_NAMES[BROKEN] = "broken"
  323.     TYPE_NAMES[PROVIDE] = "provide"
  324.     TYPE_NAMES[PARALLEL] = "parallel"
  325.     TYPE_NAMES[MTIME] = "mtime"
  326.  
  327.     # Get our environment variables
  328.     SVCDIR = ENVIRON["SVCDIR"]
  329.     if (SVCDIR == "") {
  330.         eerror("Could not get SVCDIR!")
  331.         exit 1
  332.     }
  333.  
  334.     # There we do not really use yet
  335.     DEPTYPES = ENVIRON["DEPTYPES"]
  336.     ORDTYPES = ENVIRON["ORDTYPES"]
  337.  
  338.     CACHEDTREE = SVCDIR "/deptree"
  339.  
  340.     assert(dosystem("rm -f " CACHEDTREE ), "system(rm -f " CACHEDTREE ")")
  341. }
  342.  
  343. {
  344.     #
  345.     # Build our DEPTREE array
  346.     #
  347.     
  348.     if ($1 == "RCSCRIPT") {
  349.         RC_NUMBER++
  350.  
  351.         DEPTREE[RC_NUMBER,NAME] = $2
  352.     }
  353.  
  354.     if ($1 == "NEED") {
  355.         sub(/NEED[[:space:]]*/, "")
  356.  
  357.         if ($0 != "")
  358.             add_deptree_item(RC_NUMBER, NEED, $0)
  359.     }
  360.  
  361.     if ($1 == "USE") {
  362.         sub(/USE[[:space:]]*/, "")
  363.  
  364.         if ($0 != "")
  365.             add_deptree_item(RC_NUMBER, USE, $0)
  366.     }
  367.  
  368.     if ($1 == "BEFORE") {
  369.         sub(/BEFORE[[:space:]]*/, "")
  370.  
  371.         if ($0 != "")
  372.             add_deptree_item(RC_NUMBER, BEFORE, $0)
  373.     }
  374.  
  375.     if ($1 == "AFTER") {
  376.         sub(/AFTER[[:space:]]*/, "")
  377.  
  378.         if ($0 != "")
  379.             add_deptree_item(RC_NUMBER, AFTER, $0)
  380.     }
  381.  
  382.     if ($1 == "PROVIDE") {
  383.         sub(/PROVIDE[[:space:]]*/, "")
  384.  
  385.         if ($0 != "")
  386.             add_deptree_item(RC_NUMBER, PROVIDE, $0)
  387.     }
  388.  
  389.     if ($1 == "PARALLEL") {
  390.         sub(/PARALLEL[[:space:]]*/, "")
  391.  
  392.         if ($0 != "")
  393.             add_deptree_item(RC_NUMBER, PARALLEL, $0)
  394.     }
  395.  
  396.     if ($1 == "MTIME") {
  397.         sub(/MTIME[[:space:]]*/, "")
  398.  
  399.         if ($0 != "") {
  400.             # We add this directly to RESOLVED_DEPTREE
  401.             add_db_entry(DEPTREE[RC_NUMBER,NAME], MTIME, $0)
  402.         }
  403.     }
  404. }
  405.  
  406. END {
  407.     # Add the 'net' service if it do not exist ...
  408.     if (!check_service("net")) {
  409.         RC_NUMBER++
  410.         DEPTREE[RC_NUMBER,NAME] = "net"
  411.     }
  412.     
  413.     # Calculate all the provides and parallels ...
  414.     for (x = 1;x <= RC_NUMBER;x++) {
  415.  
  416.         if ((x,PROVIDE) in DEPTREE)
  417.             add_provide(DEPTREE[x,NAME], DEPTREE[x,PROVIDE])
  418.             
  419.         if ((x,PARALLEL) in DEPTREE)
  420.             add_parallel(DEPTREE[x,NAME], DEPTREE[x,PARALLEL])
  421.     }
  422.  
  423.     # Now do NEED, USE, BEFORE and AFTER
  424.     for (x = 1;x <= RC_NUMBER;x++) {
  425.     
  426.         if ((x,NEED) in DEPTREE)
  427.             resolve_depend(NEED, DEPTREE[x,NAME], DEPTREE[x,NEED])
  428.  
  429.         if ((x,USE) in DEPTREE)
  430.             resolve_depend(USE, DEPTREE[x,NAME], DEPTREE[x,USE])
  431.  
  432.         if ((x,BEFORE) in DEPTREE)
  433.             resolve_depend(BEFORE, DEPTREE[x,NAME], DEPTREE[x,BEFORE])
  434.  
  435.         if ((x,AFTER) in DEPTREE)
  436.             resolve_depend(AFTER, DEPTREE[x,NAME], DEPTREE[x,AFTER])
  437.     }
  438.  
  439.     for (x = TYPES_MIN; x <= TYPES_MAX; x++)
  440.         print "rc_type_" TYPE_NAMES[x] "=" x >> (CACHEDTREE)
  441.     print "rc_index_scale=" (TYPES_MAX + 1) >> (CACHEDTREE)
  442.     print "" >> (CACHEDTREE)
  443.     print "declare -a RC_DEPEND_TREE" >> (CACHEDTREE)
  444.     print "" >> (CACHEDTREE)
  445.     print "RC_DEPEND_TREE[0]=" RC_NUMBER >> (CACHEDTREE)
  446.     print "" >> (CACHEDTREE)
  447.  
  448.     # Generate the resolved CACHEDTREE
  449.     #
  450.     # NOTE:  We used to use depinfo_<scriptname>() function to resolve our
  451.     #        rc_<type> variables, but that do not scale when the names of
  452.     #        the scripts include invalid bash variable characters (+,.,etc).
  453.     #
  454.     for (x = 1;x <= RC_NUMBER;x++) {
  455.  
  456.         print "RC_DEPEND_TREE[" (x * (TYPES_MAX + 1)) "]=\"" DEPTREE[x,NAME] "\"" >> (CACHEDTREE)
  457.  
  458.         for (y = TYPES_MIN; y <= TYPES_MAX; y++) {
  459.  
  460.             tmpname = "RC_DEPEND_TREE[" (x * (TYPES_MAX + 1)) "+" y "]"
  461.  
  462.             if ((x,y) in RESOLVED_DEPTREE) {
  463.             
  464.                 split(RESOLVED_DEPTREE[x,y], tmparray1)
  465.                 count = asort(tmparray1, tmparray2)
  466.                 tmpstr = tmparray2[1]
  467.                 
  468.                 for (i = 2;i <= count;i++)
  469.                     tmpstr = tmpstr " " tmparray2[i]
  470.                 
  471.                 print tmpname "=\"" tmpstr "\"" >> (CACHEDTREE)
  472.             } else
  473.                 print tmpname "=" >> (CACHEDTREE)
  474.         }
  475.  
  476.         print "" >> (CACHEDTREE)
  477.     }
  478.  
  479.     # Do not export these, as we want them local
  480.     print "RC_GOT_DEPTREE_INFO=\"yes\"" >> (CACHEDTREE)
  481.     print "" >> (CACHEDTREE)
  482.  
  483.     if (check_provide("logger"))
  484.         print "LOGGER_SERVICE=\"" get_provide("logger") "\"" >> (CACHEDTREE)
  485.     else
  486.         print "LOGGER_SERVICE=" >> (CACHEDTREE)
  487.         
  488.     close(CACHEDTREE)
  489. }
  490.  
  491.  
  492. # vim:ts=4
  493.